<template>
  <div class="parent_container">
    <div class="part_container">
      <div ref="container1"></div>
      <div class="control_container">
        <label>
          宽度：{{ width1 }}
          <input type="range" min="10" max="200" v-model="width1" />
        </label>
        <label>
          高度：{{ height1 }}
          <input type="range" min="10" max="200" v-model="height1" />
        </label>
        <label>
          深度：{{ depth1 }}
          <input type="range" min="10" max="200" v-model="depth1" />
        </label>
      </div>
    </div>

    <div class="part_container">
      <div ref="container2"></div>
      <div class="control_container">
        <label>
          宽度：{{ width2 }}
          <input type="range" min="10" max="200" v-model="width2" />
        </label>
        <label>
          高度：{{ height2 }}
          <input type="range" min="10" max="200" v-model="height2" />
        </label>
        <label>
          深度：{{ depth2 }}
          <input type="range" min="10" max="200" v-model="depth2" />
        </label>
        <label>
          横向片段：{{ widthSegments2 }}
          <input type="range" min="2" max="10" v-model="widthSegments2" />
        </label>
        <label>
          纵向片段：{{ heightSegments2 }}
          <input type="range" min="2" max="10" v-model="heightSegments2" />
        </label>
        <label>
          深度片段：{{ depthSegments2 }}
          <input type="range" min="2" max="10" v-model="depthSegments2" />
        </label>
      </div>
    </div>

    <div class="part_container">
      <div ref="container3"></div>
      <div class="control_container">
        <label>
          半径：{{ radius1 }}
          <input type="range" min="10" max="200" v-model="radius1" />
        </label>
        <label>
          片段：{{ segments1 }}
          <input type="range" min="1" max="30" v-model="segments1" />
        </label>
        <label>
          start theta：{{ thetaStart1 }}
          <input
            type="range"
            min="0"
            max="2"
            step="0.01"
            v-model="thetaStart1"
          />
        </label>
        <label>
          theta length：{{ thetaLength1 }}
          <input
            type="range"
            min="0"
            max="2"
            step="0.01"
            v-model="thetaLength1"
          />
        </label>
      </div>
    </div>

    <div class="part_container">
        <div ref="container4"></div>
        <div class="control_container">
          <label>
            半径：{{ radius2 }}
            <input type="range" min="10" max="50" v-model="radius2" />
          </label>
          <label>
            高度：{{ height3 }}
            <input type="range" min="10" max="200" v-model="height3" />
          </label>
          <label>
            radialSegments：{{ radialSegments }}
            <input type="range" min="1" max="50" step="0.01" v-model="radialSegments" />
          </label>
          <label>
            heightSegments：{{ heightSegments3 }}
            <input
              type="range"
              min="1"
              max="10"
              step="0.01"
              v-model="heightSegments3"
            />
          </label>
          <label>
            open ended：{{ openEnded }}
            <input type="checkbox" v-model="openEnded"/>
          </label>
          <label>
            start theta：{{ thetaStart2 }}
            <input
              type="range"
              min="0"
              max="2"
              step="0.01"
              v-model="thetaStart2"
            />
          </label>
          <label>
            theta length：{{ thetaLength2 }}
            <input
              type="range"
              min="0"
              max="2"
              step="0.01"
              v-model="thetaLength2"
            />
          </label>
        </div>
      </div>
  </div>
</template>

<script setup lang="ts">
import { ref, onMounted, watch } from "vue";
import ThreeScene from "@/utils/ThreeScene";
import * as THREE from "three";

//示例1
const container1 = ref<HTMLElement>();
const width1 = ref(80);
const height1 = ref(80);
const depth1 = ref(80);

//示例2
const container2 = ref<HTMLElement>();
const width2 = ref(80);
const height2 = ref(80);
const depth2 = ref(80);
const widthSegments2 = ref(3);
const heightSegments2 = ref(3);
const depthSegments2 = ref(3);

const container3 = ref<HTMLElement>();
const radius1 = ref(50);
const segments1 = ref(10);
const thetaStart1 = ref(0.6);
const thetaLength1 = ref(1.5);

const container4 = ref<HTMLElement>();
const radius2 = ref(50);
const height3 = ref(50);
const radialSegments = ref(10);
const heightSegments3 = ref(5);
const openEnded = ref(false);
const thetaStart2 = ref(0.6);
const thetaLength2 = ref(1.5);


function example1() {
  //示例1
  const threeScene = new ThreeScene(300, 300, container1.value);
  const geometry = new THREE.BoxGeometry(
    width1.value,
    height1.value,
    depth1.value
  );
  const material = new THREE.MeshStandardMaterial({
    color: 0x00ff99,
    metalness: 0.5,
    roughness: 0.1,
  });
  const cube = new THREE.Mesh(geometry, material);
  cube.position.set(0, 0, 0);
  threeScene.addObject(cube);
  threeScene.addUpdate(() => {
    cube.rotation.x += 0.01;
    cube.rotation.y += 0.01;
  });
  watch([width1, height1, depth1], () => {
    if (cube) {
      const newGeometry = new THREE.BoxGeometry(
        width1.value,
        height1.value,
        depth1.value
      );
      cube.geometry.dispose();
      cube.geometry = newGeometry;
    }
  });
}

function example2() {
  //示例2
  const threeScene2 = new ThreeScene(300, 300, container2.value);
  const geometry2 = new THREE.BoxGeometry(
    width2.value,
    height2.value,
    depth2.value,
    widthSegments2.value,
    heightSegments2.value,
    depthSegments2.value
  );
  const material2 = new THREE.MeshStandardMaterial({
    color: 0x00ff99,
    metalness: 0.5,
    roughness: 0.1,
  });
  const cube2 = new THREE.Mesh(geometry2, material2);

  //为cube创建线框
  let wireframe = new THREE.LineSegments(
    new THREE.WireframeGeometry(geometry2),
    new THREE.LineBasicMaterial({
      color: 0xffffff,
      transparent: true,
      opacity: 1,
    })
  );
  cube2.add(wireframe);

  cube2.position.set(0, 0, 0);
  threeScene2.addObject(cube2);
  threeScene2.addUpdate(() => {
    cube2.rotation.x += 0.01;
    cube2.rotation.y += 0.01;
  });
  watch(
    [width2, height2, depth2, widthSegments2, heightSegments2, depthSegments2],
    () => {
      if (cube2) {
        const newGeometry = new THREE.BoxGeometry(
          width2.value,
          height2.value,
          depth2.value,
          widthSegments2.value,
          heightSegments2.value,
          depthSegments2.value
        );
        cube2.geometry.dispose();
        cube2.geometry = newGeometry;
        //重建线框
        cube2.remove(wireframe);
        wireframe = new THREE.LineSegments(
          new THREE.WireframeGeometry(newGeometry),
          new THREE.LineBasicMaterial({
            color: 0xffffff,
            transparent: true,
            opacity: 1,
          })
        );
        cube2.add(wireframe);
      }
    }
  );
}

function example3() {
  const threeScene = new ThreeScene(300, 300, container3.value);
  const geometry = new THREE.CircleGeometry(
    radius1.value,
    segments1.value,
    thetaStart1.value * Math.PI,
    thetaLength1.value * Math.PI
  );
  const material = new THREE.MeshStandardMaterial({
    color: 0x00ff99,
    metalness: 0.5,
    roughness: 0.1,
    side: THREE.DoubleSide,
  });
  const circle = new THREE.Mesh(geometry, material);
  threeScene.addObject(circle);

  let wireframe: any = new THREE.LineSegments(
    new THREE.WireframeGeometry(geometry),
    new THREE.LineBasicMaterial({
      color: 0xffffff,
      transparent: true,
      opacity: 1,
    })
  );
  circle.add(wireframe);

  threeScene.addUpdate(() => {
    circle.rotation.y += 0.01;
    circle.rotation.x += 0.01;
  });
  watch([radius1, segments1, thetaStart1, thetaLength1], () => {
    const geometry = new THREE.CircleGeometry(
      radius1.value,
      segments1.value,
      thetaStart1.value * Math.PI,
      thetaLength1.value * Math.PI
    );
    circle.geometry.dispose();
    circle.geometry = geometry;
    circle.remove(wireframe);
    circle.add(
      (wireframe = new THREE.LineSegments(
        geometry,
        new THREE.LineBasicMaterial({})
      ))
    );
  });
}

function example4() {
    const scene = new ThreeScene(300, 300, container4.value);
    const geometry = new THREE.ConeGeometry(
      radius2.value,
      height3.value,
      radialSegments.value,
      heightSegments3.value,
      openEnded.value,
      thetaStart2.value * Math.PI,
      thetaLength2.value * Math.PI
    ); 
    const material = new THREE.MeshStandardMaterial({
        color: 0x00ff99,
        metalness: 0.5,
        roughness: 0.1,
        side: THREE.DoubleSide,
    });

    const cone = new THREE.Mesh(geometry, material); 
    scene.addObject(cone);
    cone.position.set(0, 0, 0);

    let lineSegments:any = new THREE.LineSegments(
      new THREE.EdgesGeometry(geometry),
      new THREE.LineBasicMaterial({ color: 0xffffff })
    );
    cone.add(lineSegments);

    scene.addUpdate(() => { 
        cone.rotation.y += 0.01;
        cone.rotation.x += 0.01;
    });

    watch([radius2,height3,radialSegments,heightSegments3,openEnded,thetaStart2,thetaLength2],()=>{
        cone.geometry.dispose();
        cone.geometry=new THREE.ConeGeometry(
            radius2.value,
            height3.value,
            radialSegments.value,
            heightSegments3.value,
            openEnded.value,
            thetaStart2.value * Math.PI,
            thetaLength2.value * Math.PI
        ); 
        cone.remove(lineSegments);
        lineSegments = new THREE.LineSegments(new THREE.WireframeGeometry(cone.geometry), new THREE.LineBasicMaterial({ color: 0xffffff }));
        cone.add(lineSegments);
    });
}

onMounted(() => {
  example1();
  example2();
  example3();
  example4();
});
</script>

<style scoped lang="scss">
$color-primary: #55c57a;

.parent_container {
  width: 100%;
  height: 100vh;
  overflow-y: auto;
  background-color: $color-primary;
}

.part_container {
  margin-top: 10px;
  display: flex;
  flex-direction: row;
}

.control_container {
  display: flex;
  margin-left: 20px;
  flex-direction: column;
  gap: 20px;
  justify-content: end;
  align-items: center;
}
</style>
